# 1.4 jfinal-undertow 高级用法

# 一、基础配置

# 1、启用配置文件

在 src/main/resources 目录下面创建 undertow.txt 文件,该文件会被 jfinal undertow 自动加载并对 jfinal undertow 进行配置。

如果不想使用 "undertow.txt" 这个文件名,还可以通过 UndertowServer.create(AppConfig.class, "other.txt") 方法的第二个参数来指定自己喜欢的文件名。

配置文件创建好以后,就可以按照下面的文档来配置相应的功能了。

# 2、常用配置

# true 值支持热加载
undertow.devMode=true
undertow.port=80
undertow.host=0.0.0.0
 
# 绝大部分情况不建议配置 context path
undertow.contextPath=/abc
1
2
3
4
5
6
7

开发时配置成 true 支持热加载,注意该 devMode 与 jfinal 项目中的 devMode 没有任何关系,注意区分。

重要:老版本的 undertow.host 配置的默认值为 localhost,Linux 操作系统下的安全设置可能无法在外网访问 localhost 下部署的项目,修改配置 undertow.host=0.0.0.0 即可。如果使用了 nginx 做了代理,可保持 localhost 配置。

# 3、web 资源加载路径配置

jfinal undertow 可以十分方便地从文件系统的目录以及 class path 或 jar 包中加载 web 静态资源,以下是配置示例:

undertow.resourcePath = src/main/webapp, classpath:static
1

如上所示 "src/main/webapp" 表示从项目根目录下的 "src/main/webapp" 下去加载 web 静态资源。 "classpath:static" 表示从 class path 以及 jar 包中的 static 路径下去加载 web 静态资源。

注意:"classpath:static" 这种配置是 jfinal undertow 1.5 才添加的功能。

undertow.resourcePath 配置的另一个重点是,以 "classpath:" 为前缀的配置需要自行注意路径是否存在,尽可能只配置存在的路径。而不以 "classpath:" 打头的配置可以将开发与部署时的路径一起配置进来(逗号分隔开),jfinal undertow 会在运行时检测路径是否存在,存在才真正让其生效,从而很方便一次配置同时适用于开发、生产两种环境。

重要:PathKit.getWebRootPath() 将指向 undertow.resourcePath 配置中的第一个有效目录,而 configEngine(Engine engine) 方法中的 engine 对象已被默认配置了 engine.setBaseTemplatePath(PathKit.getWebRootPath())。所以该配置与 engine 的 baseTemplatePath 有关联。

# 4、性能配置

# io 线程数与 worker 线程数
# undertow.ioThreads=
# undertow.workerThreads=
1
2
3

默认配置已充分考虑常用场景,如果没有压测数据作为指导,建议使用默认配置,不要添加这两项配置。

ioThreads 为 NIO 处理 io 请求的线程数量,在生产环境下建议的配置范围是 cpu 核心数的一倍到两倍。建议根据压测结果进行调整。

workerThreads 是处理请求的线程数量,在生产环境下可以使用默认配置,或者根据压测结果进行配置。在压测数据几乎最好的情况下尽可能选择更小的 workThreads 值。因为当性能达到某个高度时再增加 workThreads 值并不会带来性能提升,但会增加系统的资源消耗。

# 5、开启 gzip 压缩

# gzip 压缩开关
undertow.gzip.enable=true
# 配置压缩级别,默认值 -1。 可配置 1 到 9。 1 拥有最快压缩速度,9 拥有最高压缩率
undertow.gzip.level=-1
# 触发压缩的最小内容长度
undertow.gzip.minLength=1024
1
2
3
4
5
6

开启 gzip 压缩可以降低网络流量,提升访问速度

# 6、配置 session

# session 过期时间,注意单位是秒
undertow.session.timeout=1800
# 支持 session 热加载,避免依赖于 session 的登录型项目反复登录,默认值为 true。仅用于 devMode,生产环境无影响
undertow.session.hotSwap=true
1
2
3
4

# 7、配置 https

# 是否开启 ssl
undertow.ssl.enable=false
# ssl 监听端口号,部署环境设置为 443
undertow.ssl.port=443
# 密钥库类型,建议使用 PKCS12
undertow.ssl.keyStoreType=PKCS12
# 密钥库文件
undertow.ssl.keyStore=demo.pfx
# 密钥库密码
undertow.ssl.keyStorePassword=123456
# 别名配置,一般不使用
undertow.ssl.keyAlias=demo
SSL 证书的获取见后面的第二小节
1
2
3
4
5
6
7
8
9
10
11
12
13

# 8、配置 http2

# ssl 开启时,是否开启 http2。检测该配置是否生效在 chrome 地址栏中输入: chrome://net-internals/#http2
undertow.http2.enable=true
1
2

开启 http2 可以大大加快访问速度,不必担心 https 比 http 慢这个事

# 9、配置 http 重定向到 https

# ssl 开启时,http 请求是否重定向到 https
undertow.http.toHttps=false
# ssl 开启时,http 请求跳转到 https 使用的状态码,默认值 302
undertow.http.toHttpsStatusCode=302
### 10、配置关闭 http
# ssl 开启时,是否关闭 http
undertow.http.disable=false
1
2
3
4
5
6
7

在启用 https 后,可以配置关闭 http,这样就只能访问 https 了。该配置项比较适合于小程序服务端。

对于一般的 web 项目不建议配置此项,而是配置 undertow.http.toHttps=true 将 http 重定向到 https

# 11、自由配置 Undertow

以上配置方式由 jfinal undertow 做了直接的支持,如果上面的配置仍然不能满足需求,还可以通过下面的方式自由配置 undertow:

UndertowServer.create(YourJFinalConfig.class)
    .onStart( builder -> {
        builder.setServerOption(UndertowOptions.参数名, 参数值);	
     })
    .start();
1
2
3
4
5

如上所示,通过在 onStart 方法中使用 builder.setServerOption(...) 可以对 underow 进行更加深入的配置,还可以调用 builder 中的其它 API 进行其它类型的配置。上述的 UndertowOptions 中定义了很多 undertow 的配置名,查看其中的注释文档可以知道还有很多有用的配置

# 12、添加 Filter、WebSocket、Servlet、Listener

特别注意,Undertow 是为嵌入而生的 Web Server,web.xml 已被抛弃,所以无法通过 web.xml 配置 web 组件。

为此 jfinal undertow 提供了 UndertowServer.configWeb(...) 可以很方便添加 Filter、WebSocket、Servlet、Listener 这些标准的 Java Web 组件:

UndertowServer.create(AppConfig.class)
     .configWeb( builder -> {
         // 配置 Filter
         builder.addFilter("myFilter", "com.abc.MyFilter");
         builder.addFilterUrlMapping("myFilter", "/*");
         builder.addFilterInitParam("myFilter", "key", "value");
         
         // 配置 Servlet
         builder.addServlet("myServlet", "com.abc.MyServlet");
         builder.addServletMapping("myServlet", "*.do");
         builder.addServletInitParam("myServlet", "key", "value");
         
         // 配置 Listener
         builder.addListener("com.abc.MyListener");
         
         // 配置 WebSocket,MyWebSocket 需使用 ServerEndpoint 注解
         builder.addWebSocketEndpoint("com.abc.MyWebSocket");
      })
     .start();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意,JFinalFilter 会接管所有请求,所以上面代码中 addServletMapping(...) 映射的 servlet 默认是无法被请求到的,需要在 configHandler(Handlers me) 中配置 UrlSkipHandler 让 jfinal 跳过这些 serlvet 的 url

以上代码中的 MyWebSocket 需要使用 ServerEndpoint 注解标识其为一个 WebSocket 组件,例如:

@ServerEndpoint("/myapp.ws")
public class MyWebSocket { 
    @OnMessage
    public void message(String message, Session session) {
        for (Session s : session.getOpenSessions()) {
            s.getAsyncRemote().sendText(message);
        }
    }
}
1
2
3
4
5
6
7
8
9

与上述 MyWebSocket 配合使用的例子 html 在这里可以下载:传送门。社区同学分享的完整 websocket 代码在这里:https://jfinal.com/share/2004

要修改一下该 html 中的 url 为: "ws://localhost:80/myapp.ws",端口号适当调整。

注意:由于 JFinalFilter 会接管所有不带 "." 字符的 URL 请求所以 @ServerEndpoint 注解中的 URL 参数值建议以 ".ws" 结尾,否则请求会响应 404 找不到资源,例如:

@ServerEndpoint("/myapp.ws")
public class MyWebSocketEndpoint  {
    ......
}
1
2
3
4

当然,ServerEndpoint 中的 URL 不使用 ".ws" 结尾也是可以的,只需要参考 jfinal 的 UrlSkipHandler 做一个 Handler 跳过属于 WebSocket 的 URL 即可

最后,websocket 支持需要添加一个依赖,要添加的依赖项请看前面的文档:https://jfinal.com/doc/1-2

# 二、SSL 证书

# 1、申请 SSL 证书

建议从阿里云或者腾迅云获取 SSL 证书,有免费版和收费版,阿里云 SSL 证书获取:SSL 证书获取传送门

注意:在申请免费版 SSL 证书的过程中,绑定域名一般输入主机名为 www 的域名,例如: www.jfinal.com

# 2、下载合适的证书类型

SSL 证书申请下来以后,可以到控制台下载证书,如下图所示:

ssl_download.png

点击下载链接以后,在右侧下载 tomcat 类型的 SSL 证书 ssl_tomcat.png

下载的证书里头,有一个 xxx.pfx 文件,该文件就是证书文件。此外还有一个 pfx-password.txt 文件,此文件里面放的是证书密码,将 xxx.pfx 放入项目的 src/main/resources 目录,在 undertow.txt 配置文件中添加如下几行配置:

# 是否开启 ssl
undertow.ssl.enable=true
# ssl 监听端口号,部署环境设置为 443
undertow.ssl.port=443
# 密钥库类型,一般是 PKCS12 与 JKS,注意根据实际类型调整
undertow.ssl.keyStoreType=PKCS12
# 密钥库文件
undertow.ssl.keyStore=demo.pfx
# 密钥库密码
undertow.ssl.keyStorePassword=123456
1
2
3
4
5
6
7
8
9
10

其中的 "demo.pfx" 即为前面下载的证书文件的文件名,"123456" 即为证书密码,这两个配置根据你下载到的实际内容进行修改。"PKCS12" 这个配置是证书类型,阿里云下载的 tomcat 型证书为 PKCS12,腾迅云可能是 "JKS"

# 3、启动项目

启动项目,通过 "https://申请证书时绑定的域名" 即可访问

# 三、Https 双向认证

如果你的 jfinal undertow 项目需要对客户端进行 ssl 认证,需要使用如下方式进行配置:

UndertowServer.create(YourJFinalConfig.class)
  .onStart( builder -> {
    builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUESTED);
  })
  .start();`
1
2
3
4
5

该方法来自于社区用户的分享:https://jfinal.com/feedback/7758

Last Updated: 9/22/2023, 9:39:45 AM